
//
//  ObjectAttribute.swift
//  Swift3.0_Study
//
//  Created by chengfeng on 2016/9/27.
//  Copyright © 2016年 zhaochengfeng. All rights reserved.
//

import Cocoa

class ObjectAttribute: NSObject {

    // ---------------类和对象----------------
    //1类的组成
    // 类==属性+下属脚本+方法
    //属性:它将值和特定的类关联
    //下属脚本:访问对象,集合的快捷方式
    //方法:实现某一特定的功能,类似于函数
    
    //2类的创建 class 类名 {
    
    //}
    
    //3实例化对象
    //var/let 对象名=类名()   ()不能少
    
    
    //----------------属性--------------
    //在OC中,属性使用关键字@property进行声明的内容,在swift中,属性可特定类,结构,或枚举关联,
    //属性一般分为存储属性,计算属性,和类型属性
    
    //1存储属性
    //存储特定类的一个常量或者变量,根据数据是否可变可以分为常量存储属性和变量存储属性
    
    //     1>定义存储属性
    // let 常量存储属性变量名:数据类型=初始值
    // var 变量存储属性变量名:数据类型=初始值
    
    func start() -> Void {
        
        class newClass {
            let value1 = 20    //初始值不可少
            var value2: Int = 0 //初始值不可少
        }
        
        //     2>访问存储属性
        //       点语法.    1.访问变量  2.修改变量
        
        let newclass = newClass()
        print( "\(newclass.value1)")
        newclass.value2 = 100
        
        
        //    3延迟存储属性
        //     若果只有在第一次调用存储属性时才确定初始值,这时需要延迟存储属性 lazy
        //    lazy var 属性名:数据类型=初始内容
        // 注意:@1延迟存储属性中的初始内容是不可以省略的,数据类型可以省略的,因为类型推断
        //      @2定义延迟属性必须用var f否则会报错
        
        
        class DataImportor {
            var fileName = 123456
        }
        
        class DataManager {
            lazy var importor = DataImportor()
            var data:String = ""
        }
        
        let manager = DataManager()
        manager.data += "more data"
        print(manager.data)
        print(manager.importor.fileName) //没调用 manager.importor.fileName 时,importor这个属性不会被创建
        
        
        
        //2.计算属性
        //计算属性不存储值,只是提供了一个getter和setter 来分别获取值和其他属性的值
        //getter一般定义方法 get {
        //   .....
        //   return 某个值
        //}
        
        //setter一般定义方法 set(参数名称) {
        //   .....
        //   属性值=某一值
        //}
        
        //计算属性同时包含getter 和setter
        
        //var 属性名:数据类型 {
        // get {
        //   .....
        //   return 某个值
        //  }
        // set(参数名称) {
        //   .....
        //   属性值=某一值
        //  }
        
        //}
        
        class WalletClass {
            var dollor = 0.0  //美元
            var cal: Double {
                get{              //顶替getter
                    let RMB = dollor * 6.2 //注意  @1必须let  @2//必须指定数据类型  @3 set()的参数的数据类型必须和返回值的数据类型相同
                    return RMB    //返回以人民币为单位的金额
                }
                set(RMB){        //定义setter
                    dollor = RMB / 6.2    //返回以美元为单位的金额
                }
            }
        }
        
        let mywallet = WalletClass()
        mywallet.cal = 20
        print(mywallet.cal)
        print(mywallet.dollor)
        
        
        //注意 @4 没有定义参数的名称 可以使用 默认名称newValue
        class WalletClass1 {
            var money = 0.0  //美元
            var cal: Double {
                get{
                    let RMB = money * 6.2 //
                    return RMB
                }
                set {
                    money = newValue / 6.2    //注意 @5 定义参数名后不能使用默认参数名 如果有了默认的newValue了,在set 加参数名同样报错
                }
            }
        }
        
        let mywallet1 = WalletClass1()
        mywallet1.cal = 200
        print(mywallet1.cal)
        print(mywallet1.money)
        
        
        //注意@6  setter 和getter的省略
        //在计算属性中,如果只有一个getter 则只成为只读计算属性.只读属性可以返回一个值,但不能设新的值
        
        class  personName {
            var name: String = ""
            var returnName: String {  //可以省略get
                if(name.isEmpty){
                    return "NULL"
                }
                else {
                    return name
                }
            }
        }
        
        let person = personName()
        print(person.returnName)
        person.name = "TOM"
        print(person.returnName)
        
        //3.类型属性
        //类型属性就是不需要对类进行实例化就可以使用的属性.他需要关键字class进行定义
        //class var 类型属性名:数据类型 {
        //....
        // 返回一个值
        //}
        
        class Cls {
            var count = 100
            static var number: Int {
                get {
                    return 10
                }
                
                set {
                    print("shie zhi ")
//                    classValue = ""
                }
            }
            class var classValue: String {
                get {
                    return "hello"
                }
                
                set {
                    number = 30
                }
                // return count
            }
        }
        print(Cls.classValue)//hello
        
        for index in Cls.classValue.characters {
            print(index)
            
        }
        
        //注意点 @1 let 不能声明类型属性  @2存储属性 类型属性不能使用存储属性
        //@3,对象不能访问类型属性,类型属性,只能使用类访问,不可以使用对象进行访问
//        var cls=Cls()
//        cls.newValue

        
        
        //属性监视器
        //属性监视器来监控和相应属性值的变化,每次属性被设置值的时候,都会调用 属性监视器,哪怕新的值和原先的值相同,属性监视器,由willSet 和 didSet 组成
        //定义方式
        /**
         *  var 属性名:数据类型:=初始值 {
         willSet(参数名) {  //在设置新的值之前被调用,他会将新的属性值作为固定参数传入
         ..
         }
         didSet(参数名) {  //在新的值设置之后调用,会将旧的属性值作为参数传入,可以为该参数名或者默认的参数名oldValue
         
         }
         
         }
         
         */
        print("--------------测试属性监控器------------")
        class StepCounter {
            var name: String = "" {
                willSet {
                    print("name will set \(newValue)")
                }
                
                didSet {
                    print("name did set \(oldValue)")
                }
            }
            
            
            var totalSteps: Int = 0 {  //千万前面不能加lazy
                willSet(newTotalSteps) {
                    print("新的值:\(newTotalSteps)")
                }
                
                didSet(old) {
                    if (totalSteps > old) {
                        print("与原来比增减了\(totalSteps - old)个值")
                    }
                    
                }
                
            }
        }
        
        let stepCounter = StepCounter()
        stepCounter.name = "你好"
        stepCounter.name = "成峰"
        
        stepCounter.totalSteps = 0
        stepCounter.totalSteps = 200
        stepCounter.totalSteps = 400
        stepCounter.totalSteps = 800

        //需要注意的事项
        // @1 当willSet()不指定 参数名时 可以使用newValue didSet()不指定参数名的时候,可以使用oldValue代替
        // @2默认参数不可以交换使用 ,也就是willSet 里的newValue 和didSet里的oldValue不可以交换使用
        // @3延迟属性不能属性监控器   var totalSteps:Int=0 前面加个lazy 就不行
        // @4分开使用willSet 和didSet. 也就是willSet 和didSet不一定成对出现 ,可以只是用willSet或者didSet
    }
}
